home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 21
/
Cream of the Crop 21 (Terry Blount) (October 1996).iso
/
program
/
freeli22.zip
/
FREELIB2.ASX
< prev
next >
Wrap
Text File
|
1996-09-01
|
73KB
|
2,710 lines
~~~C_STR1
Ideal
Public strlen,strcpy,strcat,strcmp
Model Tiny
CodeSeg
P186
;****************** strlen() -- Get length of string
;int strlen(char *strp);
strp equ bp+4
Proc strlen
push bp ;Set up stack frame
mov bp,sp
push si ;Save SI
mov si,[strp] ;SI = string pointer
p1_loop: lodsb ;Load char
test al,al ;Loop while not zero
jnz p1_loop
sub si,[strp] ;AX = length
dec si
xchg ax,si
pop si ;Restore SI
pop bp ;Delete stack frame
ret 2 ;Return
EndP strlen
;****************** strcpy() -- Copy a string
;void strcpy(char *str1, char *str2);
str1 equ bp+6
str2 equ bp+4
Proc strcpy
push bp ;Set up stack frame
mov bp,sp
pusha ;Save all registers
mov si,[str2] ;SI = source
mov di,[str1] ;DI = destination
p2_loop: lodsb ;Load char
mov [di],al ;Store char
inc di
test al,al ;Loop while not zero
jnz p2_loop
popa ;Restore registers
pop bp ;Delete stack frame
ret 4 ;Return
EndP strcpy
;****************** strcat() -- Concatenate strings
;void strcat(char *str1, char *str2);
str1 equ bp+6
str2 equ bp+4
Proc strcat
push bp ;Set up stack frame
mov bp,sp
pusha ;Save all registers
mov si,[str1] ;SI = destination
p3_cloop: lodsb ;Load char
test al,al ;Loop while not zero
jnz p3_cloop
mov di,si ;DI = destination
mov si,[str2] ;SI = source
dec di
p3_loop: lodsb ;Load char
mov [di],al ;Store char
inc di
test al,al ;Loop while not zero
jnz p3_loop
popa ;Restore registers
pop bp ;Delete stack frame
ret 4 ;Return
EndP strcat
;****************** strcmp() -- Compare strings
;void strcmp(char *str1, char *str2);
str1 equ bp+6
str2 equ bp+4
Proc strcmp
push bp ;Set up stack frame
mov bp,sp
push si di ;Save registers
mov si,[str1] ;SI = source
mov di,[str2] ;DI = destination
p4_loop: lodsb ;Load char 1
mov ah,[di] ;Load char 2
inc di
cmp al,ah ;Not equal?
jne p4_nope
test al,al ;Loop while not zero
jnz p4_loop
xor ax,ax ;Equal, return 0
p4_done: pop di si ;Restore registers
pop bp ;Delete stack frame
ret 4 ;Return
p4_nope: sub al,ah ;Not equal, return difference
cbw ;in first unequal position
jmp p4_done
EndP strcmp
End
~~~C_STR2
Ideal
Extrn strlen:near
Public strchr,strstr
Model Tiny
CodeSeg
P186
;****************** strchr() -- Search string for char
;int strchr(char *strp, int chr);
strp equ bp+6
chr equ bp+4
Proc strchr
push bp ;Set up stack frame
mov bp,sp
push si ;Save SI
mov si,[strp] ;SI = string pointer
mov ah,[chr] ;AH = char
p1_loop: lodsb ;Load char
test al,al ;Null, not found
jz p1_nope
cmp al,ah ;Loop while not equal
jne p1_loop
sub si,[strp] ;AX = position of char
dec si
xchg ax,si
p1_done: pop si ;Restore SI
pop bp ;Delete stack frame
ret 4 ;Return
p1_nope: mov ax,-1 ;Not found, return -1
jmp p1_done
EndP strchr
;****************** strstr() -- Search string for substring
;int strstr(char *strp, char *subp);
strp equ bp+6
subp equ bp+4
Proc strstr
push bp ;Set up stack frame
mov bp,sp
pusha ;Save registers
push es
push ds ;ES = DS
pop es
mov si,[strp] ;SI = string pointer
mov bx,[subp] ;BX = substring pointer
push bx ;Get length of substring
call strlen ;into DX
xchg dx,ax
mov ah,[bx] ;AH = first char
p3_loop: lodsb ;Load char
test al,al ;Null, not found
jz p3_nope
cmp al,ah ;Loop while not equal
jne p3_loop
mov cx,dx ;CX = length
mov di,bx ;DI = substring
push si ;Save SI
dec si ;Push back char
repe cmpsb ;Compare strings
pop si ;Restore SI
jne p3_loop ;Loop if not equal
sub si,[strp] ;AX = position of char
dec si
p3_done: mov [bp-2],si ;Change pushed AX
pop es ;Restore registers
popa
pop bp ;Delete stack frame
ret 4 ;Return
p3_nope: mov si,-1 ;Not found, return -1
jmp p3_done
EndP strstr
End
~~~C_STR3
Ideal
Public stricmp,strlwr,strupr
Model Tiny
CodeSeg
P186
;****************** stricmp() -- Compare strings, case insensitive
;void stricmp(char *str1, char *str2);
str1 equ bp+6
str2 equ bp+4
Proc stricmp
push bp ;Set up stack frame
mov bp,sp
push si di ;Save registers
mov si,[str1] ;SI = source
mov di,[str2] ;DI = destination
p1_loop: lodsb ;Load char 1
mov ah,[di] ;Load char 2
inc di
cmp al,'a' ;Convert AL to uppercase
jb p1_setAH
cmp al,'z'
ja p1_setAH
sub al,20h
p1_setAH: cmp ah,'a' ;Convert AH to uppercase
jb p1_comp
cmp ah,'z'
ja p1_comp
sub ah,20h
p1_comp: cmp al,ah ;Equal?
jne p1_nope
test al,al ;Loop while not zero
jnz p1_loop
inc ax ;Equal, return 1
p1_done: pop di si ;Restore registers
pop bp ;Delete stack frame
ret 4 ;Return
p1_nope: xor ax,ax ;Not equal, return 0
jmp p1_done
EndP stricmp
;****************** strlwr() -- Convert string to lowercase
;int strlwr(char *strp);
strp equ bp+4
Proc strlwr
push bp ;Set up stack frame
mov bp,sp
pusha ;Save registers
mov si,[strp] ;SI = string pointer
p2_loop: lodsb ;Load char
test al,al ;Check for null
jz p2_done
cmp al,'A' ;Check for uppercase
jb p2_loop
cmp al,'Z'
ja p2_loop
add al,20h ;Convert to lowercase
mov [si-1],al ;Store char
jmp p2_loop
p2_done: popa ;Restore registers
pop bp ;Delete stack frame
ret 2 ;Return
EndP strlwr
;****************** strupr() -- Convert string to uppercase
;int strupr(char *strp);
strp equ bp+4
Proc strupr
push bp ;Set up stack frame
mov bp,sp
pusha ;Save registers
mov si,[strp] ;SI = string pointer
p3_loop: lodsb ;Load char
test al,al ;Check for null
jz p3_done
cmp al,'a' ;Check for lowercase
jb p3_loop
cmp al,'z'
ja p3_loop
sub al,20h ;Convert to uppercase
mov [si-1],al ;Store char
jmp p3_loop
p3_done: popa ;Restore registers
pop bp ;Delete stack frame
ret 2 ;Return
EndP strupr
End
~~~C_STR4
Ideal
Public strrtrim,strltrim
Model Tiny
CodeSeg
P186
;****************** strrtrim() -- Trim trailing spaces off a string
;int strrtrim(char *strp);
strp equ bp+4
Proc strrtrim
push bp ;Set up stack frame
mov bp,sp
pusha ;Save registers
mov si,[strp] ;SI = string pointer
mov di,si ;DI = SI
p1_loop: lodsb ;Load char
test al,al ;Check for null
jz p1_done
cmp al,' ' ;Check for space
je p1_loop
mov di,si ;Set pointer
jmp p1_loop
p1_done: mov [byte di+1],al ;Terminate string
popa ;Restore registers
pop bp ;Delete stack frame
ret 2 ;Return
EndP strrtrim
;****************** strltrim() -- Trim leading spaces off a string
;int strltrim(char *strp);
strp equ bp+4
Proc strltrim
push bp ;Set up stack frame
mov bp,sp
pusha ;Save registers
mov si,[strp] ;SI, DI = string pointer
mov di,si
p2_loop: lodsb ;Load char
test al,al ;Check for null
jz p2_cont
cmp al,' ' ;Loop while space
je p2_loop
p2_cont: dec si ;Move back one char
cmp si,di ;No spaces, quit
je p2_done
p2_cloop: lodsb ;Shift the string over
mov [di],al
inc di
test al,al
jnz p2_cloop
p2_done: popa ;Restore registers
pop bp ;Delete stack frame
ret 2 ;Return
EndP strltrim
End
~~~C_MEM1
Ideal
Public memcpy,memset
Model Tiny
CodeSeg
P186
;****************** memcpy() -- Copy memory block
;void memcpy(void *p1, void *p2, int nbytes);
p1 equ bp+8
p2 equ bp+6
nbytes equ bp+4
Proc memcpy
push bp ;Set up stack frame
mov bp,sp
push es ;Save registers
pusha
push ds ;ES = DS
pop es
mov si,[p2] ;SI = source
mov di,[p1] ;DI = destination
mov cx,[nbytes] ;CX = count
cmp di,si ;Make forward moves
jb p1_go ;in reverse
je p1_done
std ;Set direction flag
add si,cx ;Move offsets to end
add di,cx
dec si
dec di
p1_go: rep movsb ;Copy memory
p1_done: cld ;Clear direction flag
popa ;Restore registers
pop es
pop bp ;Delete stack frame
ret 6 ;Return
EndP memcpy
;****************** memset() -- Set memory block
;void memset(void *ptr, int nbytes, int chr);
ptr equ bp+8
nbytes equ bp+6
chr equ bp+4
Proc memset
push bp ;Set up stack frame
mov bp,sp
push es ;Save registers
pusha
push ds ;ES = DS
pop es
mov di,[ptr] ;DI = block
mov cx,[nbytes] ;CX = count
mov al,[chr] ;AL = char
rep stosb ;Set memory
popa ;Restore registers
pop es
pop bp ;Delete stack frame
ret 6 ;Return
EndP memset
End
~~~C_MEM2
Ideal
Public memcmp,memchr
Model Tiny
CodeSeg
P186
;****************** memcmp() -- Compare memory blocks
;void memcmp(void *p1, void *p2, int nbytes);
p1 equ bp+8
p2 equ bp+6
nbytes equ bp+4
Proc memcmp
push bp ;Set up stack frame
mov bp,sp
push es ;Save registers
push cx si di
push ds ;ES = DS
pop es
mov si,[p2] ;SI = source
mov di,[p1] ;DI = destination
mov cx,[nbytes] ;CX = count
repe cmpsb ;Compare memory
mov ax,1 ;Assume equal
je p1_done ;Jump if equal
xor ax,ax ;Not equal, return 0
p1_done: pop di si cx ;Restore registers
pop es
pop bp ;Delete stack frame
ret 6 ;Return
EndP memcmp
;****************** memchr() -- Scan memory for char
;void memchr(void *ptr, int nbytes, int chr);
ptr equ bp+8
nbytes equ bp+6
chr equ bp+4
Proc memchr
push bp ;Set up stack frame
mov bp,sp
push es ;Save registers
push cx si di
push ds ;ES = DS
pop es
mov di,[ptr] ;DI = block
mov cx,[nbytes] ;CX = count
mov al,[chr] ;AL = char
repne scasb ;Scan memory
jne p2_nope ;Jump if not found
sub di,[ptr] ;AX = position of char
dec di
xchg ax,di
p2_done: pop di si cx ;Restore registers
pop es
pop bp ;Delete stack frame
ret 6 ;Return
p2_nope: mov ax,-1 ;Not found, return -1
jmp p2_done
EndP memchr
End
~~~C_ISRCH
Ideal
Public isearch
Model Tiny
P186
CodeSeg
;****************** isearch() -- Search a sorted array of integers
;int isearch(int *ary, int size, int elem);
ary equ bp+8
size equ bp+6
elem equ bp+4
Proc isearch
push bp ;Set up stack frame
mov bp,sp
push bx cx dx si di ;Save registers
mov bx,[ary] ;BX = array
xor cx,cx ;CX = lower limit
mov dx,[size] ;DX = upper limit
dec dx
p1_loop: mov si,cx ;SI = middle element
add si,dx
shr si,1
add si,si
mov ax,[bx+si] ;Get element
shr si,1 ;Fix SI
cmp ax,[elem] ;Check element
je p1_found ;Equal?
jl p1_less ;Too low?
p1_greater: mov di,si ;Set first half
mov si,cx
jmp p1_cont
p1_less: mov di,dx ;Set second half
inc si
p1_cont: cmp cx,dx ;Min = Max, done
je p1_nope
mov cx,si ;Set limits
mov dx,di
jmp p1_loop ;Loop back
p1_found: xchg ax,si ;AX = result
p1_done: pop di si dx cx bx ;Restore registers
pop bp ;Delete stack frame
ret 6 ;Return
p1_nope: mov ax,-1 ;Not found, return -1
jmp p1_done
EndP isearch
End
~~~C_LSRCH
Ideal
Public lsearch
Model Tiny
P186
CodeSeg
;****************** lsearch() -- Search a sorted array of longs
;int lsearch(long *ary, int size, long elem);
ary equ bp+10
size equ bp+8
elem equ bp+4
Proc lsearch
push bp ;Set up stack frame
mov bp,sp
push bx cx dx si di ;Save registers
mov bx,[ary] ;BX = array
xor cx,cx ;CX = lower limit
mov dx,[size] ;DX = upper limit
dec dx
p1_loop: mov si,cx ;SI = middle element
add si,dx
shr si,1
shl si,2
mov ax,[bx+si] ;Get element
mov di,[bx+si+2]
shr si,2 ;Fix SI
cmp di,[elem+2] ;Check high word
jl p1_less ;Too low?
jg p1_greater ;Too high?
cmp ax,[elem] ;Check low word
je p1_found ;Equal?
jl p1_less ;Too low?
p1_greater: mov di,si ;Set first half
mov si,cx
dec di
jmp p1_cont
p1_less: mov di,dx ;Set second half
inc si
p1_cont: cmp cx,dx ;Min = Max, done
je p1_nope
mov cx,si ;Set limits
mov dx,di
jmp p1_loop ;Loop back
p1_found: xchg ax,si ;AX = result
p1_done: pop di si dx cx bx ;Restore registers
pop bp ;Delete stack frame
ret 8 ;Return
p1_nope: mov ax,-1 ;Not found, return -1
jmp p1_done
EndP lsearch
End
~~~C_XSRCH
Ideal
Public xsearch
Model Tiny
P186
CodeSeg
;****************** xsearch() -- Search sorted array, generalized
;int xsearch(void **ary, int size, void *elem, void *func);
ary equ bp+10
size equ bp+8
elem equ bp+6
func equ bp+4
Proc xsearch
push bp ;Set up stack frame
mov bp,sp
push bx cx dx si di ;Save registers
mov bx,[ary] ;BX = array
xor cx,cx ;CX = lower limit
mov dx,[size] ;DX = upper limit
dec dx
p3_loop: mov si,cx ;SI = middle element
add si,dx
shr si,1
add si,si
mov ax,[bx+si] ;Get element
shr si,1 ;Fix SI
push ax [elem] ;Check element
call [word func]
test ax,ax
je p3_found ;Equal?
jl p3_less ;Too low?
p3_greater: mov di,si ;Set first half
mov si,cx
jmp p3_cont
p3_less: mov di,dx ;Set second half
inc si
p3_cont: cmp cx,dx ;Min = Max, done
je p3_nope
mov cx,si ;Set limits
mov dx,di
jmp p3_loop ;Loop back
p3_found: xchg ax,si ;AX = result
p3_done: pop di si dx cx bx ;Restore registers
pop bp ;Delete stack frame
ret 8 ;Return
p3_nope: mov ax,-1 ;Not found, return -1
jmp p3_done
EndP xsearch
End
~~~C_SSRCH
Ideal
Extrn strcmp:near
Public ssearch
Model Tiny
P186
CodeSeg
;****************** ssearch() -- Search a sorted array of strings
;int ssearch(char **ary, int size, char *elem);
ary equ bp+8
size equ bp+6
elem equ bp+4
Proc ssearch
push bp ;Set up stack frame
mov bp,sp
push bx cx dx si di ;Save registers
mov bx,[ary] ;BX = array
xor cx,cx ;CX = lower limit
mov dx,[size] ;DX = upper limit
dec dx
p1_loop: mov si,cx ;SI = middle element
add si,dx
shr si,1
add si,si
mov ax,[bx+si] ;Get element
shr si,1 ;Fix SI
push ax [elem] ;Check element
call strcmp
test ax,ax
je p1_found ;Equal?
jl p1_less ;Too low?
p1_greater: mov di,si ;Set first half
mov si,cx
jmp p1_cont
p1_less: mov di,dx ;Set second half
inc si
p1_cont: cmp cx,dx ;Min = Max, done
je p1_nope
mov cx,si ;Set limits
mov dx,di
dec di
jmp p1_loop ;Loop back
p1_found: xchg ax,si ;AX = result
p1_done: pop di si dx cx bx ;Restore registers
pop bp ;Delete stack frame
ret 6 ;Return
p1_nope: mov ax,-1 ;Not found, return -1
jmp p1_done
EndP ssearch
End
~~~C_ISORT
Ideal
Public isort
Model Tiny
P186
CodeSeg
;****************** isort() -- Sort an array of integers
;void isort(int *ary, int size);
ary equ bp+6
max equ bp+4
Proc isort
push bp ;Set up stack frame
mov bp,sp
pusha ;Save all registers
mov bx,[ary] ;Call recursive routine
xor cx,cx
mov dx,[max]
dec dx
add dx,dx
call p1_qsort
popa ;Restore registers
pop bp ;Delete stack frame
ret 4 ;Return
p1_qsort: cmp cx,dx ;One element, return
je p1_ret
pusha
mov ax,dx ;Two elements, sort them
sub ax,cx
cmp ax,2
jne p1_cont
mov si,cx ;SI, DI = low, high
mov di,dx
mov ax,[bx+si] ;Check them
cmp ax,[bx+di]
jle p1_done
xchg ax,[bx+di] ;Switch them
mov [bx+si],ax
jmp p1_done
p1_cont: mov si,cx ;AX = middle element
add si,dx
shr si,2
add si,si
mov ax,[bx+si]
mov si,cx ;SI = low, DI = high
mov di,dx
p1_loop: cmp si,dx ;While [BX+SI] < AX and
jge p1_loop2 ; SI < DX, advance SI
cmp ax,[bx+si]
jle p1_loop2
inc si
inc si
jmp p1_loop
p1_loop2: cmp di,cx ;While [BX+DI] > AX and
jle p1_cont2 ; DI > CX, advance DI
cmp ax,[bx+di]
jge p1_cont2
dec di
dec di
jmp p1_loop2
p1_cont2: cmp si,di ;Hit in middle, recurse
jge p1_rec
push [bx+si] ;Swap elements
push [bx+di]
pop [bx+si]
pop [bx+di]
inc si ;Advance SI, DI
inc si
dec di
dec di
jmp p1_loop ;Loop back
p1_rec: cmp cx,si ;If first half isn't empty,
je p1_skip1 ;recurse to sort it
xchg dx,di
call p1_qsort
xchg dx,di
p1_skip1: cmp dx,di ;If second half isn't empty,
je p1_done ;recurse to sort it
xchg cx,si
call p1_qsort
xchg cx,si
p1_done: popa ;Restore registers
p1_ret: ret ;Return
EndP isort
End
~~~C_LSORT
Ideal
Public lsort
Model Tiny
P186
CodeSeg
;****************** lsort() -- Sort an array of longs
;void lsort(long *ary, int size);
ary equ bp+6
max equ bp+4
num equ bp-4
Proc lsort
enter 4,0 ;Set up stack frame
pusha ;Save all registers
mov bx,[ary] ;Call recursive routine
xor cx,cx
mov dx,[max]
dec dx
shl dx,2
call p1_qsort
popa ;Restore registers
leave ;Delete stack frame
ret 4 ;Return
p1_done: popa ;Restore registers
p1_ret: ret ;Return
p1_qsort: cmp cx,dx ;One element, return
je p1_ret
pusha
mov ax,dx ;Two elements, sort them
sub ax,cx
cmp ax,4
jne p1_cont
mov si,cx ;SI, DI = low, high
mov di,dx
mov dx,[bx+si+2] ;Check them
mov ax,[bx+si]
cmp dx,[bx+di+2]
jl p1_done
jg p1_swap2
cmp ax,[bx+di]
jle p1_done
p1_swap2: xchg ax,[bx+di] ;Switch them
mov [bx+si],ax
xchg dx,[bx+di+2]
mov [bx+si+2],dx
jmp p1_done
p1_cont: mov si,cx ;NUM = middle element
add si,dx
shr si,3
shl si,2
mov ax,[bx+si]
mov [num],ax
mov ax,[bx+si+2]
mov [num+2],ax
mov si,cx ;SI = low, DI = high
mov di,dx
p1_loop: cmp si,dx ;While [BX+SI] < NUM and
jge p1_loop2 ; SI < DX, advance SI
mov ax,[num+2]
cmp ax,[bx+si+2]
jl p1_loop2
jg p1_go1
mov ax,[num]
cmp ax,[bx+si]
jle p1_loop2
p1_go1: add si,4
jmp p1_loop
p1_loop2: cmp di,cx ;While [BX+DI] > NUM and
jle p1_cont2 ; DI > CX, advance DI
mov ax,[num+2]
cmp ax,[bx+di+2]
jg p1_cont2
jl p1_go2
mov ax,[num]
cmp ax,[bx+di]
jge p1_cont2
p1_go2: sub di,4
jmp p1_loop2
p1_cont2: cmp si,di ;Hit in middle, recurse
jge p1_rec
push [bx+si] ;Swap elements
push [bx+di]
pop [bx+si]
pop [bx+di]
push [bx+si+2]
push [bx+di+2]
pop [bx+si+2]
pop [bx+di+2]
add si,4 ;Advance SI, DI
sub di,4
jmp p1_loop ;Loop back
p1_rec: cmp cx,si ;If first half isn't empty,
je p1_skip1 ;recurse to sort it
xchg dx,di
call p1_qsort
xchg dx,di
p1_skip1: cmp dx,di ;If second half isn't empty,
je p1_done2 ;recurse to sort it
xchg cx,si
call p1_qsort
xchg cx,si
p1_done2: jmp p1_done ;Return
EndP lsort
End
~~~C_SSORT
Ideal
Extrn strcmp:near
Public ssort
Model Tiny
P186
CodeSeg
;****************** ssort() -- Sort an array of strings
;void ssort(char **ary, int size);
ary equ bp+6
max equ bp+4
Proc ssort
push bp ;Set up stack frame
mov bp,sp
pusha ;Save all registers
mov bx,[ary] ;Call recursive routine
xor cx,cx
mov dx,[max]
dec dx
add dx,dx
call p1_qsort
popa ;Restore registers
pop bp ;Delete stack frame
ret 4 ;Return
p1_qsort: cmp cx,dx ;One element, return
jne $+3
ret
pusha
mov ax,dx ;Two elements, sort them
sub ax,cx
cmp ax,2
jne p1_cont
mov si,cx ;SI, DI = low, high
mov di,dx
mov ax,[bx+si] ;Check them
push ax [bx+di]
call strcmp
test ax,ax
jle p1_done
push [bx+si] ;Switch them
push [bx+di]
pop [bx+si]
pop [bx+di]
jmp p1_done
p1_cont: mov si,cx ;AX = middle element
add si,dx
shr si,2
add si,si
mov ax,[bx+si]
mov si,cx ;SI = low, DI = high
mov di,dx
p1_loop: cmp si,dx ;While [BX+SI] < AX and
jge p1_loop2 ; SI < DX, advance SI
push ax ax [bx+si]
call strcmp
pop ax
jle p1_loop2
inc si
inc si
jmp p1_loop
p1_loop2: cmp di,cx ;While [BX+DI] > AX and
jle p1_cont2 ; DI > CX, advance DI
push ax ax [bx+di]
call strcmp
pop ax
jge p1_cont2
dec di
dec di
jmp p1_loop2
p1_cont2: cmp si,di ;Hit in middle, recurse
jge p1_rec
push [bx+si] ;Swap elements
push [bx+di]
pop [bx+si]
pop [bx+di]
inc si ;Advance SI, DI
inc si
dec di
dec di
jmp p1_loop ;Loop back
p1_rec: cmp cx,si ;If first half isn't empty,
je p1_skip1 ;recurse to sort it
xchg dx,di
call p1_qsort
xchg dx,di
p1_skip1: cmp dx,di ;If second half isn't empty,
je p1_done ;recurse to sort it
xchg cx,si
call p1_qsort
xchg cx,si
p1_done: popa ;Restore registers
p1_ret: ret ;Return
EndP ssort
End
~~~C_XSORT
Ideal
Public xsort
Model Tiny
P186
CodeSeg
;****************** xsort() -- Sort array, generalized
;void xsort(void **ary, int size, void *func);
ary equ bp+8
max equ bp+6
func equ bp+4
Proc xsort
push bp ;Set up stack frame
mov bp,sp
pusha ;Save all registers
mov bx,[ary] ;Call recursive routine
xor cx,cx
mov dx,[max]
dec dx
add dx,dx
call p1_qsort
popa ;Restore registers
pop bp ;Delete stack frame
ret 4 ;Return
p1_qsort: cmp cx,dx ;One element, return
jne $+3
ret
pusha
mov ax,dx ;Two elements, sort them
sub ax,cx
cmp ax,2
jne p1_cont
mov si,cx ;SI, DI = low, high
mov di,dx
mov ax,[bx+si] ;Check them
push ax [bx+di]
call [word func]
test ax,ax
jle p1_done
push [bx+si] ;Switch them
push [bx+di]
pop [bx+si]
pop [bx+di]
jmp p1_done
p1_cont: mov si,cx ;AX = middle element
add si,dx
shr si,2
add si,si
mov ax,[bx+si]
mov si,cx ;SI = low, DI = high
mov di,dx
p1_loop: cmp si,dx ;While [BX+SI] < AX and
jge p1_loop2 ; SI < DX, advance SI
push ax ax [bx+si]
call [word func]
pop ax
jle p1_loop2
inc si
inc si
jmp p1_loop
p1_loop2: cmp di,cx ;While [BX+DI] > AX and
jle p1_cont2 ; DI > CX, advance DI
push ax ax [bx+di]
call [word func]
pop ax
jge p1_cont2
dec di
dec di
jmp p1_loop2
p1_cont2: cmp si,di ;Hit in middle, recurse
jge p1_rec
push [bx+si] ;Swap elements
push [bx+di]
pop [bx+si]
pop [bx+di]
inc si ;Advance SI, DI
inc si
dec di
dec di
jmp p1_loop ;Loop back
p1_rec: cmp cx,si ;If first half isn't empty,
je p1_skip1 ;recurse to sort it
xchg dx,di
call p1_qsort
xchg dx,di
p1_skip1: cmp dx,di ;If second half isn't empty,
je p1_done ;recurse to sort it
xchg cx,si
call p1_qsort
xchg cx,si
p1_done: popa ;Restore registers
p1_ret: ret ;Return
EndP xsort
End
~~~C_LSHL
Ideal
Public lshl
Model Tiny
CodeSeg
P186
;****************** lshl() -- Shift long integer to the left
;long lshl(long x, int d); 37 clocks (486)
x equ bp+6
d equ bp+4
Proc lshl
push bp ;Set up stack frame
mov bp,sp
push cx ;Save CX
mov ax,[x] ;DX:AX = x
mov dx,[x+2]
mov cl,[d] ;CL = distance
cmp cl,16 ;Distance > 16?
jb p1_cont ;Jump if not
mov dx,ax ;Shift left 16
xor ax,ax
p1_cont: and cl,15 ;Mask off high part
push ax cx ;Save AX, CX
shl dx,cl ;DX = (DX shl CL) +
xor cl,15 ; (AX shr (16 - CL))
inc cx
shr ax,cl
add dx,ax
pop cx ax ;Restore AX, CX
shl ax,cl ;AX = AX shl CL
pop cx ;Restore CX
pop bp ;Delete stack frame
ret 6 ;Return
EndP lshl
End
~~~C_LSHR
Ideal
Public lshr
Model Tiny
CodeSeg
P186
;****************** lshr() -- Shift long integer to the right
;long lshr(long x, int d); 37 clocks (486)
x equ bp+6
d equ bp+4
Proc lshr
push bp ;Set up stack frame
mov bp,sp
push cx ;Save CX
mov ax,[x] ;DX:AX = x
mov dx,[x+2]
mov cl,[d] ;CL = distance
cmp cl,16 ;Distance > 16?
jb p1_cont ;Jump if not
mov ax,dx ;Shift right 16
xor dx,dx
p1_cont: and cl,15 ;Mask off high part
push dx cx ;Save DX, CX
shr ax,cl ;AX = (AX shr CL) +
xor cl,15 ; (DX shl (16 - CL))
inc cx
shl dx,cl
add ax,dx
pop cx dx ;Restore DX, CX
shr dx,cl ;DX = DX shr CL
pop cx ;Restore CX
pop bp ;Delete stack frame
ret 6 ;Return
EndP lshr
End
~~~C_LSAR
Ideal
Public lsar
Model Tiny
CodeSeg
P186
;****************** lsar() -- Shift long integer to the right, signed
;long lsar(long x, int d); 39 clocks (486)
x equ bp+6
d equ bp+4
Proc lsar
push bp ;Set up stack frame
mov bp,sp
push cx ;Save CX
mov ax,[x] ;DX:AX = x
mov dx,[x+2]
mov cl,[d] ;CL = distance
cmp cl,16 ;Distance > 16?
jb p1_cont ;Jump if not
mov ax,dx ;Shift right 16
cbw
p1_cont: and cl,15 ;Mask off high part
push dx cx ;Save DX, CX
shr ax,cl ;AX = (AX shr CL) +
xor cl,15 ; (DX shl (16 - CL))
inc cx
shl dx,cl
add ax,dx
pop cx dx ;Restore DX, CX
sar dx,cl ;DX = DX sar CL
pop cx ;Restore CX
pop bp ;Delete stack frame
ret 6 ;Return
EndP lsar
End
~~~C_LMUL
Ideal
Public lmul
Model Tiny
CodeSeg
P186
;****************** lmul() -- Multiply long integers
;long lmul(long x, long y); 70 clocks (486)
x equ bp+8
y equ bp+4
Proc lmul
push bp ;Set up stack frame
mov bp,sp
push bx ;Save registers
mov ax,[x] ;Multiply low words
mul [word y]
mov bx,dx ;BX = high word
push ax ;Save low word
mov ax,[x+2] ;Multiply high by low Y
mul [word y]
add bx,ax ;Add in result
mov ax,[y+2] ;Multiply high by low X
mul [word x]
add ax,bx ;Add in result
pop dx ;Restore low word
xchg dx,ax ;DX:AX = result
pop bx ;Restore registers
pop bp ;Delete stack frame
ret 8 ;Return
EndP lmul
End
~~~C_LIMUL
Ideal
Public limul
Model Tiny
CodeSeg
P186
;****************** limul() -- Multiply long integers, signed
;long limul(long x, long y); 89-97 clocks (486)
x equ bp+8
y equ bp+4
Proc limul
push bp ;Set up stack frame
mov bp,sp
push bx cx ;Save registers
xor cx,cx ;Clear neg flag
mov ax,[x+2] ;AX = x high word
test ax,ax ;Negative?
jge p1_xok
neg ax ;Negate X
neg [word x]
sbb ax,0
not cx ;Set neg flag
p1_xok: mov [x+2],ax ;Save X
mov ax,[y+2] ;AX = y high word
test ax,ax ;Negative?
jge p1_yok
neg ax ;Negate Y
neg [word y]
sbb ax,0
not cx ;Flip neg flag
p1_yok: mov [y+2],ax ;Save Y
mov ax,[x] ;Multiply low words
mul [word y]
mov bx,dx ;BX = high word
push ax ;Save low word
mov ax,[x+2] ;Multiply high by low Y
mul [word y]
add bx,ax ;Add in result
mov ax,[y+2] ;Multiply high by low X
mul [word x]
add ax,bx ;Add in result
pop dx ;Restore low word
xchg dx,ax ;DX:AX = result
test cx,cx ;Check neg flag
jz p1_done
neg dx ;Negate result
neg ax
sbb dx,0
p1_done: pop cx bx ;Restore registers
pop bp ;Delete stack frame
ret 8 ;Return
EndP limul
End
~~~C_LDIV
Ideal
Public ldiv
Model Tiny
CodeSeg
P186
;****************** ldiv() -- Divide long integers
;long ldiv(long x, long y); 692-948 clocks (486)
x equ bp+8
y equ bp+4
Proc ldiv
push bp ;Set up stack frame
mov bp,sp
push bx cx si ;Save registers
xor ax,ax ;Clear DX:AX, CX:BX
xor bx,bx ;DX:AX will contain
xor cx,cx ;the result, and
xor dx,dx ;CX:BX will be X.
mov si,32 ;SI = count
p1_loop: shl [word x],1 ;Shift in one bit of X
rcl [word x+2],1
adc bx,bx
adc cx,cx
add ax,ax ;Shift result left by 1
adc dx,dx
cmp cx,[y+2] ;Compare the partial X
jb p1_skip ;to Y, if X is bigger
ja p1_sub ;then Y is subtracted
cmp bx,[y] ;from the partial X.
jb p1_skip
p1_sub: sub bx,[y] ;Subtract Y from partial X
sbb cx,[y+2]
add ax,1 ;Add one bit to result
adc dx,0
p1_skip: dec si ;Loop back
jnz p1_loop
pop si cx bx ;Restore registers
pop bp ;Delete stack frame
ret 8 ;Return
EndP ldiv
End
~~~C_LIDIV
Ideal
Public lidiv
Model Tiny
CodeSeg
P186
;****************** lidiv() -- Divide long integers, signed
;long lidiv(long x, long y); 711-975 clocks (486)
x equ bp+8
y equ bp+4
Proc lidiv
push bp ;Set up stack frame
mov bp,sp
push bx cx si ;Save registers
xor cx,cx ;Clear neg flag
mov ax,[x+2] ;AX = x high word
test ax,ax ;Negative?
jge p1_xok
neg ax ;Negate X
neg [word x]
sbb ax,0
not cx ;Set neg flag
p1_xok: mov [x+2],ax ;Save X
mov ax,[y+2] ;AX = y high word
test ax,ax ;Negative?
jge p1_yok
neg ax ;Negate Y
neg [word y]
sbb ax,0
not cx ;Flip neg flag
p1_yok: mov [y+2],ax ;Save Y
push cx ;Save neg flag
xor ax,ax ;Clear DX:AX, CX:BX
xor bx,bx ;DX:AX will contain
xor cx,cx ;the result, and
xor dx,dx ;CX:BX will be X.
mov si,32 ;SI = count
p1_loop: shl [word x],1 ;Shift in one bit of X
rcl [word x+2],1
adc bx,bx
adc cx,cx
add ax,ax ;Shift result left by 1
adc dx,dx
cmp cx,[y+2] ;Compare the partial X
jb p1_skip ;to Y, if X is bigger
ja p1_sub ;then Y is subtracted
cmp bx,[y] ;from the partial X.
jb p1_skip
p1_sub: sub bx,[y] ;Subtract Y from partial X
sbb cx,[y+2]
add ax,1 ;Add one bit to result
adc dx,0
p1_skip: dec si ;Loop back
jnz p1_loop
pop cx ;Restore neg flag
test cx,cx ;Check neg flag
jz p1_done
neg dx ;Negate result
neg ax
sbb dx,0
p1_done: pop si cx bx ;Restore registers
pop bp ;Delete stack frame
ret 8 ;Return
EndP lidiv
End
~~~C_LMOD
Ideal
Extrn ldiv:near,lmul:near
Public lmod
Model Tiny
CodeSeg
P186
;****************** lmod() -- Modulo on long integers
;long lmod(long x, long y);
x equ bp+8
y equ bp+4
Proc lmod
push bp ;Set up stack frame
mov bp,sp
push [x] [x+2] ;x MOD y = x - (x / y) * y
push [y] [y+2]
call ldiv
push [y] [y+2]
push dx ax
call lmul
neg dx ;Negate, add in X
neg ax
sbb dx,0
add ax,[x]
adc dx,[x+2]
pop bp ;Delete stack frame
ret 8 ;Return
EndP lmod
End
~~~C_LIMOD
Ideal
Extrn lidiv:near,limul:near
Public limod
Model Tiny
CodeSeg
P186
;****************** limod() -- Modulo on long integers, signed
;long limod(long x, long y);
x equ bp+8
y equ bp+4
Proc limod
push bp ;Set up stack frame
mov bp,sp
push [x] [x+2] ;x MOD y = x - (x / y) * y
push [y] [y+2]
call lidiv
push [y] [y+2]
push dx ax
call limul
neg dx ;Negate, add in X
neg ax
sbb dx,0
add ax,[x]
adc dx,[x+2]
pop bp ;Delete stack frame
ret 8 ;Return
EndP limod
End
~~~C_FIXMUL
Ideal
Public fixmul
Model Tiny
CodeSeg
P186
;****************** fixmul() -- Multiply fixed point numbers
;long fixmul(long x, long y); 101-109 clocks (486)
x equ bp+8
y equ bp+4
Proc fixmul
push bp ;Set up stack frame
mov bp,sp
push bx cx si ;Save registers
xor si,si ;Clear neg flag
mov ax,[x+2] ;AX = x high word
test ax,ax ;Negative?
jge p1_xok
neg ax ;Negate X
neg [word x]
sbb ax,0
not si ;Set neg flag
p1_xok: mov [x+2],ax ;Save X
mov ax,[y+2] ;AX = y high word
test ax,ax ;Negative?
jge p1_yok
neg ax ;Negate Y
neg [word y]
sbb ax,0
not si ;Flip neg flag
p1_yok: mov [y+2],ax ;Save Y
mov ax,[x+2] ;Multiply high by low Y
mul [word y]
mov cx,dx ;Save in CX:BX
xchg bx,ax
mov ax,[y+2] ;Multiply high by low X
mul [word x]
add bx,ax ;Add in result
adc cx,dx
mov ax,[x] ;Multiply low words
mul [word y]
add bx,dx ;Add in result
adc cx,0
mov ax,[x+2] ;Multiply high words
mul [word y+2]
add ax,cx ;Add in result
mov dx,bx ;DX:AX = result
xchg dx,ax
test si,si ;Check neg flag
jz p1_done
neg dx ;Negate result
neg ax
sbb dx,0
p1_done: pop si cx bx ;Restore registers
pop bp ;Delete stack frame
ret 8 ;Return
EndP fixmul
End
~~~C_FIXDIV
Ideal
Public fixdiv
Model Tiny
CodeSeg
P186
;****************** fixdiv() -- Divide fixed point numbers
;long fixdiv(long x, long y); 1028-1412 clocks (486)
x equ bp+8
y equ bp+4
Proc fixdiv
push bp ;Set up stack frame
mov bp,sp
push bx cx si ;Save registers
xor cx,cx ;Clear neg flag
mov ax,[x+2] ;AX = x high word
test ax,ax ;Negative?
jge p1_xok
neg ax ;Negate X
neg [word x]
sbb ax,0
not cx ;Set neg flag
p1_xok: mov [x+2],ax ;Save X
mov ax,[y+2] ;AX = y high word
test ax,ax ;Negative?
jge p1_yok
neg ax ;Negate Y
neg [word y]
sbb ax,0
not cx ;Flip neg flag
p1_yok: mov [y+2],ax ;Save Y
push cx ;Save neg flag
xor ax,ax ;Clear DX:AX, CX:BX
xor bx,bx ;DX:AX will contain
xor cx,cx ;the result, and
xor dx,dx ;CX:BX will be X.
mov si,48 ;SI = count
p1_loop: shl [word x],1 ;Shift in one bit of X
rcl [word x+2],1
adc bx,bx
adc cx,cx
add ax,ax ;Shift result left by 1
adc dx,dx
cmp cx,[y+2] ;Compare the partial X
jb p1_skip ;to Y, if X is bigger
ja p1_sub ;then Y is subtracted
cmp bx,[y] ;from the partial X.
jb p1_skip
p1_sub: sub bx,[y] ;Subtract Y from partial X
sbb cx,[y+2]
add ax,1 ;Add one bit to result
adc dx,0
p1_skip: dec si ;Loop back
jnz p1_loop
pop cx ;Restore neg flag
test cx,cx ;Check neg flag
jz p1_done
neg dx ;Negate result
neg ax
sbb dx,0
p1_done: pop si cx bx ;Restore registers
pop bp ;Delete stack frame
ret 8 ;Return
EndP fixdiv
End
~~~C_TRIG
Ideal
Extrn fixmul:near, fixdiv:near
Public sine, cosine, tangent, cotangent
Public secant, cosecant
Model Tiny
CodeSeg
P186
;****************** TaylorSine() -- Calculate sine by Taylor series
;long TaylorSine(long x);
; *──────────────────────────────────────────────────*
; │ x^3 x^5 x^7 x^9 │
; │ sin(x) = x - ───── + ───── - ───── + ───── - ... │
; │ 3 ! 5 ! 7 ! 9 ! │
; *──────────────────────────────────────────────────*
x equ bp+4
Proc TaylorSine
enter 2,0 ;Set up stack frame
push bx cx si di ;Save registers
mov dx,[x+2] ;First term = x
mov ax,[x]
xor cx,cx ;Result = 0
xor bx,bx
mov [word bp-2],1 ;Count = 1
TS_loop: add bx,ax ;Add in term
adc cx,dx
mov si,[x] ;DI:SI = x
mov di,[x+2]
push dx ax di si ;term = last-term * x
call fixmul
push dx ax di si ;term = last-term * x^2
call fixmul
mov di,dx ;DI:SI = term
xchg si,ax
add [word bp-2],2 ;n = n + 2
mov ax,[bp-2] ;AX = n
mov dx,[bp-2] ;DX = n - 1
dec dx
mul dx ;AX = n * (n - 1)
push di si ax 0 ;term = last-term * x^2 / n(n-1)
call fixdiv ;the next term in the series
neg dx ;Invert sign
neg ax
sbb dx,0
test ax,ax ;Loop while not zero
jnz TS_loop
test dx,dx
jnz TS_loop
xchg ax,bx ;Result in DX:AX
mov dx,cx
pop di si cx bx ;Restore registers
leave ;Delete stack frame
ret 4 ;Return
EndP TaylorSine
Pi dd 0003243Fh ;Pi (3.243F6A88... hex)
TwoPi dd 0006487Fh ;Pi*2 (6.487ED511... hex)
HalfPi dd 00019220h ;Pi/2 (1.921FB544... hex)
;****************** sine() -- Trigonometric sine function
;long sine(long x);
x equ bp+4
Proc sine
push bp ;Set up stack frame
mov bp,sp
mov dx,[x+2] ;DX:AX = x
mov ax,[x]
add ax,[word Pi] ; x + Pi
adc dx,[word Pi+2]
push dx ax ;Divide by 2*Pi
push [word TwoPi+2]
push [word TwoPi]
call fixdiv
xor ax,ax ;Convert to integer
push dx ax ;Multiply by 2*Pi
push [word TwoPi+2]
push [word TwoPi]
call fixmul
neg dx ;Negate...
neg ax
sbb dx,0
add ax,[x] ;Add in X
adc dx,[x+2]
push dx ax ;Calculate sine
call TaylorSine
pop bp ;Delete stack frame
ret 4 ;Return
EndP sine
;****************** cosine() -- Trigonometric cosine function
;long cosine(long x);
x equ bp+4
Proc cosine
push bp ;Set up stack frame
mov bp,sp
mov dx,[x+2] ;DX:AX = x
mov ax,[x]
add ax,[word HalfPi] ; x + Pi+2
adc dx,[word HalfPi+2]
push dx ax ;cos(x) = sin(x + Pi/4)
call sine
pop bp ;Delete stack frame
ret 4 ;Return
EndP cosine
;****************** tangent() -- Trigonometric tangent function
;long tangent(long x);
x equ bp+4
Proc tangent
push bp ;Set up stack frame
mov bp,sp
push bx cx ;Save registers
push [x+2] [x] ;CX:BX = sin(x)
call sine
mov cx,dx
xchg bx,ax
push [x+2] [x] ;DX:AX = cos(x)
call cosine
push cx bx dx ax ;tan(x) = sin(x) / cos(x)
call fixdiv
pop cx bx ;Restore registers
pop bp ;Delete stack frame
ret 4 ;Return
EndP tangent
;****************** cotangent() -- Trigonometric cotangent function
;long cotangent(long x);
x equ bp+4
Proc cotangent
push bp ;Set up stack frame
mov bp,sp
push bx cx ;Save registers
push [x+2] [x] ;CX:BX = sin(x)
call sine
mov cx,dx
xchg bx,ax
push [x+2] [x] ;DX:AX = cos(x)
call cosine
push dx ax cx bx ;cot(x) = cos(x) / sin(x)
call fixdiv
pop cx bx ;Restore registers
pop bp ;Delete stack frame
ret 4 ;Return
EndP cotangent
;****************** secant() -- Trigonometric secant function
;long secant(long x);
x equ bp+4
Proc secant
push bp ;Set up stack frame
mov bp,sp
push [x+2] [x] ;DX:AX = cos(x)
call cosine
push 1 0 dx ax ;sec(x) = 1 / cos(x)
call fixdiv
pop bp ;Delete stack frame
ret 4 ;Return
EndP secant
;****************** cosecant() -- Trigonometric cosecant function
;long cosecant(long x);
x equ bp+4
Proc cosecant
push bp ;Set up stack frame
mov bp,sp
push [x+2] [x] ;DX:AX = cos(x)
call sine
push 1 0 dx ax ;csc(x) = 1 / sin(x)
call fixdiv
pop bp ;Delete stack frame
ret 4 ;Return
EndP cosecant
End
~~~C_FIXTOA
Ideal
Public fixtoa
Model Tiny
CodeSeg
P186
;****************** fixtoa() -- Convert fixed point number to string
;void fixtoa(int n, char *strp);
n equ bp+6
strp equ bp+4
Proc fixtoa
push bp ;Set up stack frame
mov bp,sp
pusha ;Save all registers
mov di,[strp] ;DI = string pointer
mov dx,[n+2] ;DX:AX = n
mov ax,[n]
test dx,dx ;Negative?
jge p1_noneg
mov [byte di],'-' ;Store minus sign
inc di
neg dx ;Make it positive
neg ax
sbb dx,0
p1_noneg: push dx ;Save DX
xor bx,bx ;Zero rem flag
add ax,ax ;Shift out high bit
adc bx,0 ;BX = rem flag
shr ax,1 ;Restore AX
mov cx,50000 ;AX = AX * 50000
mul cx
shr ax,15 ;AX = AX / 32768
shl dx,1
or ax,dx
pop dx ;Restore DX
push bx ax ;Save BX, AX
xchg dx,ax ;Integer part in AX
xor cx,cx ;Zero CX
mov si,10 ;SI = 10
p1_dloop: xor dx,dx ;Divide by 10
div si
mov bl,dl ;Remainder in BL
add bl,30h ;Convert to digit
push bx ;Push digit
inc cx
test ax,ax ;Loop back
jnz p1_dloop
p1_ploop: pop ax ;Pop digit
mov [di],al ;Store digit
inc di
loop p1_ploop ;Loop back
mov [byte di],'.' ;Store decimal point
inc di
pop ax bx ;Restore low data
xor dx,dx ;Zero DX
test bx,bx ;Check for high part
jz p1_nohigh
add ax,50000 ;Add in 50000
adc dx,0
p1_nohigh: mov si,10 ;SI = 10
mov cx,5 ;5 digits
jmp p1_skip1
p1_dloopb: xor dx,dx ;Zero DX
p1_skip1: div si ;Divide by 10
mov bl,dl ;Remainder in BL
add bl,30h ;Convert to digit
push bx ;Push digit
loop p1_dloopb ;Loop back
mov cx,5 ;5 digits
p1_ploopb: pop ax ;Pop digit
mov [di],al ;Store digit
inc di
loop p1_ploopb ;Loop back
mov [byte di],0 ;Add the null byte
p1_done: popa ;Restore registers
pop bp ;Delete stack frame
ret 6 ;Return
EndP fixtoa
End
~~~C_ATOFIX
Ideal
Public atofix
Model Tiny
CodeSeg
P186
;****************** atofix() -- Convert string to fixed point number
;long atofix(char *strp);
strp equ bp+4
Proc atofix
push bp ;Set up stack frame
mov bp,sp
push bx cx si di bp ;Save registers
mov si,[strp] ;SI = string
xor ax,ax ;AX = 0
xor bh,bh ;BH = 0
mov cx,10 ;CX = 10
p1_ploop: mov bl,[si] ;Load char
inc si
cmp bl,' ' ;Loop while char is space
je p1_ploop ;(20h, or 09h thru 0Dh)
cmp bl,9
jna p1_go
cmp bl,13
jbe p1_ploop
p1_go: xor bp,bp ;BP = 0
cmp bl,'+' ;If char = '+', ignore
je p1_loop
cmp bl,'-' ;If char <> '-', keep it
jne p1_skip
inc bp ;Set negative flag
p1_loop: mov bl,[si] ;Load char
inc si
p1_skip: xor dx,dx ;Clear DX
cmp bl,'.' ;Decimal point, continue
je p1_cont
cmp bl,'9' ;Not a digit, finish
ja p1_finish
sub bl,'0'
jc p1_finish
mul cx ;Multiply by 10
add ax,bx ;Add in digit...
jmp p1_loop ;Loop back
p1_cont: push ax ;Save integer part
xor ax,ax ;Zero AX
mov di,1 ;DI = 1
p1_floop: mov bl,[si] ;Load char
inc si
cmp bl,'9' ;Not a digit, finish
ja p1_ffinish
sub bl,'0'
jc p1_ffinish
mul cx ;Multiply by 10
add ax,bx ;Add in digit...
adc dx,0
imul di,10 ;Multiply divisor by 10
jnc p1_floop ;Loop while < 5 digits
shr dx,1 ;5 digits, divide by 2
rcr ax,1 ;and set DI to 50000
mov di,50000 ;instead of 100000
p1_ffinish: xchg dx,ax ;Multiply by 65536
xor ax,ax
div di ;Divide by 10^digits
xchg dx,ax ;Fractional part in DX
pop ax ;Restore integer part
p1_finish: xchg dx,ax ;DX:AX = number
dec bp ;Positive, don't negate
jl p1_done
neg dx ;Negate the result
neg ax
sbb dx,0
p1_done: pop bp di si cx bx ;Restore registers
pop bp ;Delete stack frame
ret 2 ;Return
EndP atofix
End
~~~C_BITS
Ideal
Public bitcnt,highbit
Model Tiny
P186
CodeSeg
;****************** bitcnt() -- Count set bits in integer
;int bitcnt(int x);
x equ bp+4
Proc bitcnt
push bp ;Set up stack frame
mov bp,sp
push bx cx ;Save registers
xor cx,cx ;CX = 0
mov ax,[x] ;AX = number
test ax,ax ;Zero?
jz p1_done
p1_loop: mov bx,ax ;Kill last bit
dec bx
and ax,bx
loopnz p1_loop ;Loop while not zero
p1_done: sub ax,cx ;Negative of CX
pop cx bx ;Restore registers
pop bp ;Delete stack frame
ret 2 ;Return
EndP bitcnt
;****************** highbit() -- Find high bit in integer
;int highbit(int x); returns -1 if it was zero
x equ bp+4
Proc highbit
push bp ;Set up stack frame
mov bp,sp
push bx ;Save registers
mov ax,15 ;Start with bit 15
mov bx,[x] ;BX = number
p2_loop: add bx,bx ;Shift out bit
jc p2_done ;Found a bit?
dec ax ;Loop back
jns p2_loop
p2_done: pop bx ;Restore registers
pop bp ;Delete stack frame
ret 2 ;Return
EndP highbit
End
~~~C_SQRT
Ideal
Public sqrt
Model Tiny
P186
CodeSeg
;****************** sqrt() -- Returns the square root of a
; long. Result is an integer.
;int sqrt(long num); 60-350 clocks (486)
num equ bp+4
Proc sqrt
push bp ;Set up stack frame
mov bp,sp
push cx dx ;Save registers
mov ax,[num] ;DX:AX = num
mov dx,[num+2]
mov cx,32 ;32 bits
p1_bloop: add ax,ax ;Find the highest set bit
adc dx,dx
jc p1_gotbit
loop p1_bloop
p1_gotbit: mov ax,1 ;CX = first guess 2^(log2(n)/2)
shr cx,1
shl ax,cl
xchg cx,ax
p1_loop: mov ax,[num] ;DX:AX = num
mov dx,[num+2]
div cx ;AX = num/guess
add cx,ax ;CX = (guess+(num/guess))/2
shr cx,1
sub ax,cx ;If the difference is 1
cmp ax,1 ;or less, then done
ja p1_loop ;Loop back
xchg ax,cx ;AX = result
pop dx cx ;Restore registers
pop bp ;Delete stack frame
ret 4 ;Return
EndP sqrt
End
~~~C_ROMAN
Ideal
Public roman
Model Tiny
CodeSeg
P386
;****************** roman() -- Convert integer to Roman Numerals
num equ bp+6
buf equ bp+4
Proc roman
push bp ;Set up stack frame
mov bp,sp
pusha ;Save all registers
mov di,[buf] ;DI = buffer
mov dx,[num] ;DX = number
mov si,offset RNTbl_1 ;SI, BX = tables
mov bx,offset RNTbl_2
p1_loop: lodsw ;Load size
test ax,ax ;Done?
jz p1_done
p1_iloop: cmp dx,ax
jl p1_lb
mov cx,[bx] ;AX = code
mov [di],cl ;Store first char
inc di
cmp ch,'.' ;If second char, then
je p1_ilb ; store second char
mov [di],ch
inc di
p1_ilb: sub dx,ax ;Reduce number
jmp p1_iloop ;Loop back
p1_lb: inc bx ;Advance pointer
inc bx
jmp p1_loop ;Loop back
p1_done: mov [di],al ;Terminate string
popa ;Restore registers
pop bp ;Delete stack frame
ret 4 ;Return
EndP roman
RNTbl_1 dw 1000,900,500,400,100
dw 90,50,40,10,9,5,4,1,0
RNTbl_2 db 'M.CMD.CDC.XCL.XLX.IXV.IVI.'
End
~~~C_CRC16
Ideal
Public crc16
Model Tiny
CodeSeg
P186
;****************** crc16() -- Calculate 16-bit CRC
;int crc16(void *ptr, int cnt)
ptr equ bp+6
cnt equ bp+4
Proc crc16
push bp ;Set up stack frame
mov bp,sp
push bx cx dx si ;Save registers
mov si,[ptr] ;SI = pointer
mov bx,[cnt] ;BX = count
xor dx,dx ;Start with 0
p1_loop: lodsb ;Load byte
xor dh,al ;XOR into result
mov cx,8 ;8 bits
p1_iloop: add dx,dx ;Shift left
jnc $+5 ;If bit = 1, then
xor dx,1021h ;XOR in CRC value
loop p1_iloop ;Loop back
dec bx ;Byte loop
jnz p1_loop
xchg dx,ax ;Result in AX
p1_done: pop si dx cx bx ;Restore registers
pop bp ;Delete stack frame
ret 4 ;Return
EndP crc16
End
~~~C_CRC32
Ideal
Public crc32
Model Tiny
CodeSeg
P186
;****************** crc32() -- Calculate 32-bit CRC
;long crc32(void *ptr, int cnt)
ptr equ bp+6
cnt equ bp+4
Proc crc32
push bp ;Set up stack frame
mov bp,sp
push bx cx si di ;Save registers
mov si,[ptr] ;SI = pointer
mov bx,[cnt] ;BX = count
xor dx,dx ;Start with 0
xor di,di
p1_loop: lodsb ;Load byte
xor dh,al ;XOR into result
mov cx,8 ;8 bits
p1_iloop: add di,di ;Shift left
adc dx,dx
jnc $+8 ;If bit = 1, then
xor dx,04C1h ;XOR in CRC value
xor di,1DB7h
loop p1_iloop ;Loop back
dec bx ;Byte loop
jnz p1_loop
xchg di,ax ;Result in DX:AX
p1_done: pop di si cx bx ;Restore registers
pop bp ;Delete stack frame
ret 4 ;Return
EndP crc32
End